
// ToolsLib Project

/* ToolsLib library for RusRoute firewall and other projects of
 * Andrey A. Moiseenko / IE Moiseenko A.A. (Russia)
 * e-mail: support@maasoftware.ru, maa2002@mail.ru
 * web: http://maasoftware.ru, http://maasoftware.com, http://maasoft.ru, http://maasoft.org
 * Author's full name: Andrey Alekseevitch Moiseenko
 * (russian name: Моисеенко Андрей Алексеевич)
 */

// ToolsLib/Console.cpp

/* Copyright (C) 2002-2024 Andrey A. Moiseenko (support@maasoftware.ru)
 * All rights reserved.
 *
 * This file contains console io working with Borland C++ 3.1 (DOS).
 * The library implementation written
 * by Andrey A. Moiseenko (support@maasoftware.ru).
 * This library and applications are
 * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
 * as long as the following conditions are aheared to.
 *
 * Copyright remains Andrey A. Moiseenko, and as such any Copyright notices in
 * the code are not to be removed.  If this code is used in a product,
 * Andrey A. Moiseenko should be given attribution as the author of the parts used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by Andrey A. Moiseenko (support@maasoftware.ru)
 *
 * THIS SOFTWARE IS PROVIDED BY ANDREY A. MOISEENKO ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */

#include "perm.h"
#include "temp.h"

//--------------------------------------------------------------------------
CMaaConsole::CMaaConsole ( HANDLE h )
{
    if  ( h == INVALID_HANDLE_VALUE )
    {
          #ifndef __BORLANDC__
        h = ::GetStdHandle ( STD_OUTPUT_HANDLE );
          #endif
    }
    m_Handle = h;
    memset ( &m_Cur, 0, sizeof ( m_Cur ) );
#ifdef __BORLANDC__
    m_Color = 0x07;
#else
    m_Color = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
#endif

}
HANDLE CMaaConsole::GetHandle ()
{
    return m_Handle;
}
void CMaaConsole::GotoXY_ ( int x, int y )
{
     #ifndef __BORLANDC__
    COORD coord;
    coord.X = x;
    coord.Y = y;
    ::SetConsoleCursorPosition ( m_Handle, coord );
     #else
    gotoxy ( x + 1, y + 1 );
     #endif
    GotoXY ( x, y );
}
void CMaaConsole::GotoXY ( int x, int y )
{
    m_Cur.X = x;
    m_Cur.Y = y;
}
BOOL CMaaConsole::WriteConsoleOutput ( const char * ptr )
{
    int len = int_strlen(ptr);
    if  ( len > 256 )
    {
        return FALSE;
    }
     #ifndef __BORLANDC__
    CHAR_INFO Buffer [ 256 ];
    for ( int i = 0; i < len; i++ )
    {
        Buffer [ i ].Char.AsciiChar = ptr [ i ];
        Buffer [ i ].Attributes = m_Color;
    }
    COORD dwBufferSize;
    dwBufferSize.X = len;
    dwBufferSize.Y = 1;
    COORD dwBufferCoord;
    dwBufferCoord.X = dwBufferCoord.Y = 0;
    SMALL_RECT WriteRegion;
    WriteRegion.Left = m_Cur.X;
    WriteRegion.Right = m_Cur.X + len - 1;
    WriteRegion.Top = m_Cur.Y;
    WriteRegion.Bottom = m_Cur.Y;
    BOOL Ret = ::WriteConsoleOutput ( m_Handle, Buffer, dwBufferSize, dwBufferCoord, &WriteRegion );
     #else
    // puttext can be used instead of direct video output
    char * pVideo = m_Cur.Y * 160 + 2 * m_Cur.X + ( char * ) MK_FP ( 0xb800, 0x0 );
    for ( int i = 0; i < len; i++ )
    {
        * pVideo = ptr [ i ];
        pVideo [ 1 ] = m_Color;
        pVideo += 2;
    }
    BOOL Ret = TRUE;
     #endif
    m_Cur.X += len;
    while( m_Cur.X > 80 )
    {
        m_Cur.Y++;
        m_Cur.X -= 80;
    }
    return Ret;
}
void CMaaConsole::printf ( const char * format, ... )
{
    char Buffer [ 1024 ];
    va_list list;
    va_start ( list, format );
    //Sprintf ( format, list );
    ::vsprintf ( Buffer, format, list );
    WriteConsoleOutput ( Buffer );
    va_end ( list );
}
BOOL CMaaConsole::IsKeyPressed ()
{
    return kbhit ();
}
int CMaaConsole::GetCh ()
{
    int c = getch ();
     #ifdef __BORLANDC__
    if  ( c == 0 )
    {
        c = ( KEY_LT & 0xff00 ) + getch ();
    }
     #else
    if  ( c == KEY_LT >> 8 || c == 0 )
    {
        if  ( c )
        {
            c = ( c << 8 ) + getch ();
        }
        else
        {
            c = ( KEY_F1 & 0xff00 ) + getch ();
        }
    }
     #endif
    return c;
}
void CMaaConsole::Cls ()
{
     #ifdef __BORLANDC__
    clrscr ();
     #else
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    if  ( ::GetConsoleScreenBufferInfo ( m_Handle, &csbi ) )
    {
        //CMaaPtr < char > Buffer ( csbi.dwSize.X + 1 );
        CMaaPtr < char > Buffer ( csbi.dwSize.X + 1 );
        if  (!Buffer.IsValid())
        {
            throw "Memory allocation error";
        }
        memset ( Buffer, ' ', csbi.dwSize.X );
        Buffer [ ( int ) csbi.dwSize.X ] = 0;
        for ( int i = csbi.dwSize.Y; i--; )
        {
            GotoXY ( 0, i );
            WriteConsoleOutput ( Buffer );
        }
        GotoXY_ ( 0, 0 );
    }
    else
    {
        ::system ( "cls" );
    }
     #endif
}

//--------------------------------------------------------------------------
